using dnAnalytics.Statistics.Distributions;
using NUnit.Framework;

namespace dnAnalytics.Tests.Statistics.Distributions
{
    [TestFixture]
    public class ConwayMaxwellPoissonTests
    {
        private const double mAcceptableError = 1e-10;

        [Test]
        public void FromNuAndLambda()
        {
            ConwayMaxwellPoisson cmp = new ConwayMaxwellPoisson(2.0, 3.0);

            Assert.AreEqual(2.0, cmp.Lambda);
            Assert.AreEqual(3.0, cmp.Nu);
        }

        [Test]
        public void PoissonSpecialCase()
        {
            // Since the Poisson is a special case of the CMP when Nu=1 we can test the mean and
            // variance computations against the Poisson distribution.
            Poisson ps = new Poisson(4.5);
            ConwayMaxwellPoisson cmp = new ConwayMaxwellPoisson(4.5, 1);

            Assert.AreEqual(ps.Mean, cmp.Mean, mAcceptableError);
            Assert.AreEqual(ps.Variance, cmp.Variance, mAcceptableError);
        }

        [Test]
        public void FromLogRatios()
        {
            // This data is from http://www.stat.cmu.edu/COM-Poisson/Sales-data.html
            double[,] salesData = { {0,514}, {1,503}, {2,457}, {3,423},
                                    {4,326}, {5,233}, {6,195}, {7,139},
                                    {8,101}, {9,77}, {10,56}, {11,40},
                                    {12,37}, {13,22}, {14,9}, {15,7},
                                    {16,10}, {17,9}, {18,3}, {19,2},
                                    {20,2}, {21,2}, {22,0}, {23,0},
                                    {24,0}, {25,0}, {26,0}, {27,0},
                                    {28,0}, {29,0}, {30,1} };

            // Get the X data.
            int[] x = new int[31];
            for (int i = 0; i < 31; i++)
            {
                x[i] = i;
            }

            // Get the count data.
            double[] c = new double[31];
            for (int i = 0; i < 31; i++)
            {
                c[i] = salesData[i, 1];
            }

            // Fit the data and check whether it is correct.
            ConwayMaxwellPoisson cmp = ConwayMaxwellPoisson.FromLogRatios(x, c);
            Assert.AreEqual(cmp.Nu, 0.0811734720745675, mAcceptableError);
            Assert.AreEqual(cmp.Lambda, 0.91500186662627, mAcceptableError);
        }

        [Test]
        public void GetSetRNG()
        {
            ConwayMaxwellPoisson cmp = new ConwayMaxwellPoisson(2.0, 3.0);

            // Try getting the random number generator.
            System.Random rnd = cmp.RandomNumberGenerator;
            // Try setting the random number generator.
            cmp.RandomNumberGenerator = new System.Random();
        }
    }
}